home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / rpcstat / rpcstat.c < prev    next >
C/C++ Source or Header  |  1992-07-10  |  26KB  |  1,049 lines

  1. /* 
  2.  * rpcStat.c --
  3.  *
  4.  *    Statistics generation, especially for the rpc module.
  5.  *
  6.  * Copyright (C) 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/cmds/rpcstat/RCS/rpcstat.c,v 1.23 92/07/10 15:16:17 kupfer Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14. #include <sprite.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <sysStats.h>
  18. #include <option.h>
  19. #include <kernel/sched.h>
  20. #include <vmStat.h>
  21. #include <host.h>
  22. #include <kernel/sync.h>
  23. #include <kernel/timer.h>
  24. #include <kernel/rpcClient.h>
  25. #include <kernel/rpcServer.h>
  26. #include <kernel/rpcCltStat.h>
  27. #include <kernel/rpcSrvStat.h>
  28. #include <kernel/rpcTrace.h>
  29. #include <kernel/rpcCall.h>
  30. #include <kernel/rpcHistogram.h>
  31.  
  32. Boolean doCltStats = FALSE;
  33. Boolean doSrvStats = FALSE;
  34. Boolean doCltState = FALSE;
  35. Boolean doSrvState = FALSE;
  36. Boolean doRpcTrace = FALSE;
  37. Boolean doCallCount = FALSE;
  38. Boolean doSrvCount = FALSE;
  39. Boolean doCltHist = FALSE;
  40. Boolean doSrvHist = FALSE;
  41. Boolean zero     = FALSE;
  42. int extraSpace = 1000;
  43. Boolean    nohostdb = FALSE;
  44.  
  45. Option optionArray[] = {
  46.     {OPT_TRUE, "trace", (Address)&doRpcTrace, "Print trace of RPCs"},
  47.     {OPT_TRUE, "cinfo", (Address)&doCltStats, "Print client RPC statistics"},
  48.     {OPT_TRUE, "sinfo", (Address)&doSrvStats, "Print server RPC statistics"},
  49.     {OPT_TRUE, "chan", (Address)&doCltState, "Print client channel state"},
  50.     {OPT_TRUE, "srvr", (Address)&doSrvState, "Print server process state"},
  51.     {OPT_TRUE, "calls", (Address)&doCallCount, "Print number of client calls"},
  52.     {OPT_TRUE, "rpcs", (Address)&doSrvCount, "Print number of service calls"},
  53.     {OPT_TRUE, "chist", (Address)&doCltHist,
  54.      "Print histogram of (client) call times"},
  55.     {OPT_TRUE, "shist", (Address)&doSrvHist,
  56.      "Print histogram of service times"},
  57.     {OPT_TRUE, "zero", (Address)&zero, "Print zero valued stats"},
  58.     {OPT_INT, "x", (Address)&extraSpace, "Extra malloc space to avoid crashes"},
  59.     {OPT_TRUE, "nohostdb", (Address)&nohostdb, "Do not search the host database"},
  60. };
  61. int numOptions = sizeof(optionArray) / sizeof(Option);
  62.  
  63. ReturnStatus status;
  64.  
  65. /* forward references: */
  66.  
  67. static void PrintCltHist();
  68. static void PrintSrvHist();
  69. static void PrintHist();
  70.  
  71.  
  72. /*
  73.  *----------------------------------------------------------------------
  74.  *
  75.  * main --
  76.  *
  77.  *    Gets options and calls printing routines.
  78.  *
  79.  * Results:
  80.  *    None.
  81.  *
  82.  * Side effects:
  83.  *    None.
  84.  *
  85.  *----------------------------------------------------------------------
  86.  */
  87.  
  88. main(argc, argv)
  89.     int argc;
  90.     char *argv[];
  91. {
  92.  
  93.     argc = Opt_Parse(argc, argv,  optionArray, numOptions, 0);
  94.  
  95.     if (doCltStats) {
  96.     PrintClientStats();
  97.     }
  98.     if (doSrvStats) {
  99.     PrintServerStats();
  100.     }
  101.     if (doCltState) {
  102.     PrintClientState();
  103.     }
  104.     if (doSrvState) {
  105.     PrintServerState();
  106.     }
  107.     if (doCallCount) {
  108.     PrintCallCount();
  109.     }
  110.     if (doSrvCount) {
  111.     PrintSrvCount();
  112.     }
  113.     if (doCltHist) {
  114.     PrintCltHist();
  115.     }
  116.     if (doSrvHist) {
  117.     PrintSrvHist();
  118.     }
  119.     if (doRpcTrace) {
  120.     PrintRpcTrace(argc, argv);
  121.     }
  122.     exit(0);
  123. }
  124.  
  125. /*
  126.  *----------------------------------------------------------------------
  127.  *
  128.  * PrintClientStats --
  129.  *
  130.  *    Prints out the low-level statistics for the client side
  131.  *    of the RPC system.
  132.  *
  133.  * Results:
  134.  *    None.
  135.  *
  136.  * Side effects:
  137.  *    None.
  138.  *
  139.  *----------------------------------------------------------------------
  140.  */
  141.  
  142. PrintClientStats()
  143. {
  144.     Rpc_CltStat rpcCltStat;
  145.  
  146.     status = Sys_Stats(SYS_RPC_CLT_STATS, TRUE, &rpcCltStat);
  147.     if (status != SUCCESS) {
  148.     return;
  149.     }
  150.     printf("Rpc Client Statistics\n");
  151.     printf("toClient   = %5d ", rpcCltStat.toClient);
  152.     printf("badChannel  = %4d ", rpcCltStat.badChannel);
  153.     printf("chanBusy    = %4d ", rpcCltStat.chanBusy);
  154.     printf("badId       = %4d ", rpcCltStat.badId);
  155.     printf("\n");
  156.     printf("requests   = %5d ", rpcCltStat.requests);
  157.     printf("replies    = %5d ", rpcCltStat.replies);
  158.     printf("acks        = %4d ", rpcCltStat.acks);
  159.     printf("recvPartial = %4d ", rpcCltStat.recvPartial);
  160.     printf("\n");
  161.     printf("nacks       = %4d ", rpcCltStat.nacks);
  162.     printf("reNacks     = %4d ", rpcCltStat.reNacks);
  163.     printf("maxNacks    = %4d ", rpcCltStat.maxNacks);
  164.     printf("timeouts    = %4d ", rpcCltStat.timeouts);
  165.     printf("\n");
  166.     printf("aborts      = %4d ", rpcCltStat.aborts);
  167.     printf("resends     = %4d ", rpcCltStat.resends);
  168.     printf("sentPartial = %4d ", rpcCltStat.sentPartial);
  169.     printf("errors      = %d(%d)", rpcCltStat.errors,
  170.                        rpcCltStat.nullErrors);
  171.     printf("\n");
  172.     printf("dupFrag     = %4d ", rpcCltStat.dupFrag);
  173.     printf("close       = %4d ", rpcCltStat.close);
  174.     printf("oldInputs   = %4d ", rpcCltStat.oldInputs);
  175.     printf("badInputs   = %4d ", rpcCltStat.oldInputs);
  176.     printf("\n");
  177.     printf("tooManyAcks = %4d ", rpcCltStat.tooManyAcks);
  178.     printf("chanHits   = %5d ", rpcCltStat.chanHits);
  179.     printf("chanNew     = %4d ", rpcCltStat.chanNew);
  180.     printf("chanReuse   = %4d ", rpcCltStat.chanReuse);
  181.     printf("\n");
  182.     printf("newTrouble  = %4d ", rpcCltStat.newTrouble);
  183.     printf("moreTrouble = %4d ", rpcCltStat.moreTrouble);
  184.     printf("endTrouble  = %4d ", rpcCltStat.endTrouble);
  185.     printf("noMark      = %4d ", rpcCltStat.noMark);
  186.     printf("\n");
  187.     printf("nackChanWait= %4d ", rpcCltStat.nackChanWait);
  188.     printf("chanWaits   = %4d ", rpcCltStat.chanWaits);
  189.     printf("chanBroads  = %4d ", rpcCltStat.chanBroads);
  190.     printf("paramOverrun = %3d ", rpcCltStat.paramOverrun);
  191.     printf("\n");
  192.     printf("dataOverrun = %4d ", rpcCltStat.dataOverrun);
  193.     printf("shorts      = %4d ", rpcCltStat.shorts);
  194.     printf("longs       = %4d ", rpcCltStat.longs);
  195.     printf("\n");
  196. }
  197.  
  198. /*
  199.  *----------------------------------------------------------------------
  200.  *
  201.  * PrintServerStats --
  202.  *
  203.  *    Prints out the low-level statistics for the service side
  204.  *    of the RPC system.
  205.  *
  206.  * Results:
  207.  *    None.
  208.  *
  209.  * Side effects:
  210.  *    None.
  211.  *
  212.  *----------------------------------------------------------------------
  213.  */
  214.  
  215. PrintServerStats()
  216. {
  217.     Rpc_SrvStat rpcSrvStat;
  218.  
  219.     status = Sys_Stats(SYS_RPC_SRV_STATS, TRUE, &rpcSrvStat);
  220.     if (status != SUCCESS) {
  221.     return;
  222.     }
  223.     printf("Rpc Server Statistics\n");
  224.     printf("toServer   = %5d ", rpcSrvStat.toServer);
  225.     printf("noAlloc     = %4d ", rpcSrvStat.noAlloc);
  226.     printf("invClient   = %4d ", rpcSrvStat.invClient);
  227.     printf("\n");
  228.     printf("nacks       = %4d ", rpcSrvStat.nacks);
  229.     printf("mostNackBufs= %4d ", rpcSrvStat.mostNackBuffers);
  230.     printf("selfNacks   = %4d ", rpcSrvStat.selfNacks);
  231.     printf("\n");
  232.     printf("serverBusy  = %4d ", rpcSrvStat.serverBusy);
  233.     printf("requests   = %5d ", rpcSrvStat.requests);
  234.     printf("impAcks    = %5d ", rpcSrvStat.impAcks);
  235.     printf("handoffs   = %5d ", rpcSrvStat.handoffs);
  236.     printf("\n");
  237.     printf("fragMsgs   = %5d ", rpcSrvStat.fragMsgs);
  238.     printf("handoffAcks = %4d ", rpcSrvStat.handoffAcks);
  239.     printf("fragAcks    = %4d ", rpcSrvStat.fragAcks);
  240.     printf("sentPartial = %4d ", rpcSrvStat.recvPartial);
  241.     printf("\n");
  242.     printf("busyAcks    = %4d ", rpcSrvStat.busyAcks);
  243.     printf("resends     = %4d ", rpcSrvStat.resends);
  244.     printf("badState    = %4d ", rpcSrvStat.badState);
  245.     printf("extra       = %4d ", rpcSrvStat.extra);
  246.     printf("\n");
  247.     printf("reclaims    = %4d ", rpcSrvStat.reclaims);
  248.     printf("reassembly = %5d ", rpcSrvStat.reassembly);
  249.     printf("dupFrag     = %4d ", rpcSrvStat.dupFrag);
  250.     printf("nonFrag     = %4d ", rpcSrvStat.nonFrag);
  251.     printf("\n");
  252.     printf("fragAborts  = %4d ", rpcSrvStat.fragAborts);
  253.     printf("recvPartial = %4d ", rpcSrvStat.recvPartial);
  254.     printf("closeAcks   = %4d ", rpcSrvStat.closeAcks);
  255.     printf("discards    = %4d ", rpcSrvStat.discards);
  256.     printf("\n");
  257.     printf("unknownAcks = %4d ", rpcSrvStat.unknownAcks);
  258.     printf("\n");
  259. }
  260.  
  261. /*
  262.  *----------------------------------------------------------------------
  263.  *
  264.  * PrintClientState --
  265.  *
  266.  *    Prints out the state of each client-side channel.
  267.  *
  268.  * Results:
  269.  *    None.
  270.  *
  271.  * Side effects:
  272.  *    None.
  273.  *
  274.  *----------------------------------------------------------------------
  275.  */
  276.  
  277. PrintClientState()
  278. {
  279.     register int index;
  280.     ReturnStatus status = SUCCESS;
  281.     RpcClientChannel *chanPtr =
  282.     (RpcClientChannel *)malloc(sizeof(RpcClientChannel) + extraSpace);
  283.  
  284.     printf("%2s  %-10s  %-15s %-8s %s\n",
  285.         "I", "RPC", "Server", "Channel", "State");
  286.     for (index=0 ; status == SUCCESS ; index++) {
  287.     status = Sys_Stats(SYS_RPC_CLT_STATE, index, (Address)chanPtr);
  288.     if (status != SUCCESS) {
  289.         break;
  290.     }
  291.     printf("%2d ", index);
  292.     PrintCommand(stdout, chanPtr->requestRpcHdr.command, " %-10s ");
  293.     PrintHostName(chanPtr->serverID, " %-15s ");
  294.     printf("%-8d ", chanPtr->requestRpcHdr.channel);
  295.     if (chanPtr->state == CHAN_FREE) {
  296.         printf("free ");
  297.     }
  298.     if (chanPtr->state & CHAN_BUSY) {
  299.         printf("busy ");
  300.     }
  301.     if (chanPtr->state & CHAN_WAITING) {
  302.         printf("wait ");
  303.     }
  304.     if (chanPtr->state & CHAN_INPUT) {
  305.         printf("input ");
  306.     }
  307.     if (chanPtr->state & CHAN_TIMEOUT) {
  308.         printf("timeout ");
  309.     }
  310.     printf("\n");
  311.     }
  312. }
  313.  
  314. /*
  315.  *----------------------------------------------------------------------
  316.  *
  317.  * PrintServerState --
  318.  *
  319.  *    Prints out state of each RPC server process.
  320.  *
  321.  * Results:
  322.  *    None.
  323.  *
  324.  * Side effects:
  325.  *    None.
  326.  *
  327.  *----------------------------------------------------------------------
  328.  */
  329.  
  330. PrintServerState()
  331. {
  332.     register int index;
  333.     ReturnStatus status = SUCCESS;
  334.     RpcServerState *srvPtr =
  335.     (RpcServerState *)malloc(sizeof(RpcServerState) + extraSpace);
  336.  
  337.     printf("%2s  %-10s  %-15s %-8s %s\n",
  338.         "I", "RPC", "Client", "Channel", "State");
  339.     for (index=0 ; status == SUCCESS ; index++) {
  340.     status = Sys_Stats(SYS_RPC_SRV_STATE, index, (Address)srvPtr);
  341.     if (status != SUCCESS) {
  342.         break;
  343.     }
  344.     printf("%2d ", index);
  345.     PrintCommand(stdout, srvPtr->requestRpcHdr.command, " %-10s ");
  346.     PrintHostName(srvPtr->clientID, " %-15s ");
  347.     printf("%-8d ", srvPtr->channel);
  348.     if (srvPtr->state == SRV_NOTREADY) {
  349.         printf("not ready");
  350.     }
  351.     if (srvPtr->state & SRV_FREE) {
  352.         printf("free ");
  353.     }
  354.     if (srvPtr->state & SRV_STUCK) {
  355.         printf("stuck ");
  356.     }
  357.     if (srvPtr->state & SRV_BUSY) {
  358.         printf("busy ");
  359.     }
  360.     if (srvPtr->state & SRV_WAITING) {
  361.         printf("wait ");
  362.     }
  363.     if (srvPtr->state & SRV_AGING) {
  364.         printf("aging (%d) ", srvPtr->age);
  365.     }
  366.     if (srvPtr->state & SRV_NO_REPLY) {
  367.         printf("no reply ");
  368.     }
  369.     if (srvPtr->state & SRV_FRAGMENT) {
  370.         printf("frag ");
  371.     }
  372.     printf("\n");
  373.     }
  374. }
  375.  
  376. /*
  377.  *----------------------------------------------------------------------
  378.  *
  379.  * PrintSrvCount --
  380.  *
  381.  *    Prints out the number of RPC calls made to this (server) host
  382.  *
  383.  * Results:
  384.  *    None.
  385.  *
  386.  * Side effects:
  387.  *    None.
  388.  *
  389.  *----------------------------------------------------------------------
  390.  */
  391.  
  392. PrintSrvCount()
  393. {
  394.     ReturnStatus status = SUCCESS;
  395.     register int call;
  396.     int rpcServiceCount[RPC_LAST_COMMAND+1];
  397.  
  398.     status = Sys_Stats(SYS_RPC_SRV_COUNTS, sizeof(rpcServiceCount),
  399.                     (Address)rpcServiceCount);
  400.     if (status != SUCCESS) {
  401.     fprintf(stderr, "Sys_Stats(SYS_RPC_SRV_COUNTS) failed <%x>\n", status);
  402.     return;
  403.     }
  404.  
  405.     printf("Rpc Service Calls\n");
  406.     for (call=0 ; call<=RPC_LAST_COMMAND ; call++) {
  407.     if (zero || rpcServiceCount[call] > 0) {
  408.         PrintCommand(stdout, call, "%-15s");
  409.         printf("%8d\n", rpcServiceCount[call]);
  410.     }
  411.     }
  412. }
  413.  
  414.  
  415. /*
  416.  *----------------------------------------------------------------------
  417.  *
  418.  * PrintCallCount --
  419.  *
  420.  *    Prints out the number of RPC calls made by this (client) host
  421.  *
  422.  * Results:
  423.  *    None.
  424.  *
  425.  * Side effects:
  426.  *    None.
  427.  *
  428.  *----------------------------------------------------------------------
  429.  */
  430.  
  431. PrintCallCount()
  432. {
  433.     ReturnStatus status = SUCCESS;
  434.     register int call;
  435.     int rpcClientCalls[RPC_LAST_COMMAND+1];
  436.  
  437.     status = Sys_Stats(SYS_RPC_CALL_COUNTS, sizeof(rpcClientCalls),
  438.                     (Address)rpcClientCalls);
  439.     if (status != SUCCESS) {
  440.     fprintf(stderr, "Sys_Stats(SYS_RPC_CALL_COUNTS) failed <%x>\n", status);
  441.     return;
  442.     }
  443.  
  444.     printf("Rpc Client Calls\n");
  445.     for (call=0 ; call<=RPC_LAST_COMMAND ; call++) {
  446.     if (zero || rpcClientCalls[call] > 0) {
  447.         PrintCommand(stdout, call, "%-15s");
  448.         printf("%8d\n", rpcClientCalls[call]);
  449.     }
  450.     }
  451. }
  452.  
  453. /*
  454.  *----------------------------------------------------------------------
  455.  *
  456.  * PrintHostName --
  457.  *
  458.  *    Prints out the host name and trims of the internet domain suffix.
  459.  *
  460.  * Results:
  461.  *    None.
  462.  *
  463.  * Side effects:
  464.  *    None.
  465.  *
  466.  *----------------------------------------------------------------------
  467.  */
  468.  
  469. PrintHostName(spriteID, format)
  470.     int spriteID;
  471.     char *format;
  472. {
  473.     Host_Entry *entryPtr;
  474.     char string[64];
  475.     char *cPtr;
  476.  
  477.     if (nohostdb) {
  478.     /*
  479.      * Don't search the /etc/spritehosts host database.  This option
  480.      * is useful for finding consist RPCs that are hung with 
  481.      * /etc/spritehosts locked.  
  482.      */
  483.     entryPtr = (Host_Entry *)NULL;
  484.     } else {
  485.     entryPtr = Host_ByID(spriteID);
  486.     }
  487.     if (entryPtr == (Host_Entry *)NULL) {
  488.     sprintf(string, "%d", spriteID);
  489.     printf(format, string);
  490.     } else {
  491.     for (cPtr = entryPtr->name ; *cPtr ; cPtr++) {
  492.         /*
  493.          * Strip off the domain suffix.
  494.          */
  495.         if (*cPtr == '.') {
  496.         *cPtr = '\0';
  497.         break;
  498.         }
  499.     }
  500.     printf(format, entryPtr->name);
  501.     }
  502. }
  503.  
  504. /*
  505.  *----------------------------------------------------------------------
  506.  *
  507.  * PrintRpcTrace --
  508.  *
  509.  *    Dump out the RPC trace.  Its a circular buffer and we'll print
  510.  *    out time delta's for each record.
  511.  *
  512.  * Results:
  513.  *    None.
  514.  *
  515.  * Side effects:
  516.  *    None.
  517.  *
  518.  *----------------------------------------------------------------------
  519.  */
  520. PrintRpcTrace(argc, argv)
  521.     int argc;
  522.     char *argv[];
  523. {
  524.     register int index;        /* index of current table entry */
  525.     Time baseTime, deltaTime;    /* Times for print out */
  526.     FILE *output;        /* Output stream */
  527.     register RpcHdr *rpcHdrPtr;    /* Rpc header stored in trace record */
  528.     Address buffer;        /* Storage for trace records */
  529.     int  bufSize;
  530.     Trace_Record *recordPtr;
  531.     int numRecords;
  532.  
  533.     if (argc > 1) {
  534.     if (strcmp("on", argv[1]) == 0) {
  535.         status = Sys_Stats(SYS_RPC_TRACE_STATS, SYS_RPC_TRACING_ON, 0);
  536.         return;
  537.     } else if (strcmp("off", argv[1]) == 0) {
  538.         status = Sys_Stats(SYS_RPC_TRACE_STATS, SYS_RPC_TRACING_OFF, 0);
  539.         return;
  540.     } else {
  541.         /*
  542.          * argv[1] is a filename - as an argument causes
  543.          * the trace dump to be written to that file.
  544.          */
  545.         output = fopen(argv[1], "w");
  546.         if (output == (FILE *)NULL) {
  547.         status = FAILURE;
  548.         return;
  549.         }
  550.     }
  551.     } else {
  552.     output = stdout;
  553.     }
  554.     /*
  555.      * Get a copy of the trace table.
  556.      */
  557.     bufSize = sizeof(int) +
  558.         RPC_TRACE_LEN * (sizeof(Trace_Record) + sizeof(RpcHdr));
  559.     buffer = (Address)malloc(bufSize);
  560.     status = Sys_Stats(SYS_RPC_TRACE_STATS, bufSize, buffer);
  561.     if (status != SUCCESS) {
  562.     return;
  563.     }
  564.  
  565.     fprintf(output, "\n");
  566. #define PRINT_HEADER() \
  567.     fprintf(output, \
  568.         "%8s %5s %8s %4s %6s %6s %6s %5s %5s %5s %8s\n", \
  569.     "ID", "code", "time", "flag", "commnd", "client", \
  570.     "server", "psize", "dsize", "doff", "fragment")
  571.     PRINT_HEADER();
  572.  
  573.     numRecords = *(int *)buffer;
  574.     buffer += sizeof(int);
  575.     recordPtr = (Trace_Record *)buffer;
  576.     rpcHdrPtr = (RpcHdr *)((int)buffer + numRecords * sizeof(Trace_Record));
  577.  
  578.     baseTime.seconds = 0;
  579.     baseTime.microseconds = 0;
  580.     for (index=0 ; index<numRecords ; index++, rpcHdrPtr++, recordPtr++) {
  581.     fprintf(output, "%8x", rpcHdrPtr->ID);
  582.     PrintType(output, recordPtr->event, " %-5s");
  583.  
  584.     Time_Subtract(recordPtr->time, baseTime, &deltaTime);
  585.     fprintf(output, " %3d.%04d",
  586.                deltaTime.seconds,
  587.                deltaTime.microseconds / 100);
  588.     baseTime = recordPtr->time;
  589.     PrintFlags(output, rpcHdrPtr->flags, " %-2s");
  590.     if (rpcHdrPtr->flags & RPC_ERROR) {
  591.         fprintf(output, " %8x", rpcHdrPtr->command);
  592.     } else {
  593.         PrintCommand(output, rpcHdrPtr->command, " %-10s");
  594.     }
  595.     fprintf(output, " %4d %d %4d %d",
  596.                rpcHdrPtr->clientID,
  597.                rpcHdrPtr->channel,
  598.                rpcHdrPtr->serverID,
  599.                rpcHdrPtr->serverHint);
  600.     fprintf(output, " %5d %5d %5d %2d %5x",
  601.                rpcHdrPtr->paramSize,
  602.                rpcHdrPtr->dataSize,
  603.                rpcHdrPtr->dataOffset,
  604.                rpcHdrPtr->numFrags,
  605.                rpcHdrPtr->fragMask);
  606.     fprintf(output, "\n");
  607.     }
  608.     PRINT_HEADER();
  609. }
  610.  
  611. /*
  612.  * PrintFlags --
  613.  *
  614.  *    Convert from bit flags to a character string and output it.
  615.  */
  616. PrintFlags(stream, flags, format)
  617.     FILE *stream;
  618.     int flags;
  619.     char *format;
  620. {
  621.     char c;
  622.     char string[10];
  623.     int index = 0;
  624.  
  625.     switch (flags & RPC_TYPE) {
  626.     case RPC_REQUEST: {
  627.         c = 'Q';
  628.         break;
  629.     }
  630.     case RPC_NACK: {
  631.         c = 'N';
  632.         break;
  633.     }
  634.     case RPC_ACK: {
  635.         c = 'A';
  636.         break;
  637.     }
  638.     case RPC_REPLY: {
  639.         c = 'R';
  640.         break;
  641.     }
  642.     case RPC_ECHO: {
  643.         c = 'E';
  644.         break;
  645.     }
  646.     default: {
  647.         c = '-';
  648.         break;
  649.     }
  650.     }
  651.     string[index] = c;
  652.     index++;
  653.     if (flags & RPC_PLSACK) {
  654.     string[index] = 'p';
  655.     index++;
  656.     }
  657.     if (flags & RPC_LASTFRAG) {
  658.     string[index] = 'f';
  659.     index++;
  660.     }
  661.     if (flags & RPC_CLOSE) {
  662.     string[index] = 'c';
  663.     index++;
  664.     }
  665.     if (flags & RPC_ERROR) {
  666.     string[index] = 'e';
  667.     index++;
  668.     }
  669.     
  670.     string[index] = '\0';
  671.     
  672.     fprintf(stream, format, string);
  673. }
  674.  
  675. /*
  676.  * PrintCommand --
  677.  *
  678.  *    Convert from procedure ID to procedure name and output it.
  679.  */
  680. PrintCommand(stream, command, format)
  681.     FILE *stream;
  682.     int command;
  683.     char *format;
  684. {
  685.     char buffer[128];
  686.     char *string;
  687.  
  688.     switch (command) {
  689.     case RPC_ECHO_1:
  690.         string = "echoIntr";
  691.         break;
  692.     case RPC_ECHO_2:
  693.         string = "echo";
  694.         break;
  695.     case RPC_SEND:
  696.         string = "send";
  697.         break;
  698.     case RPC_RECEIVE:
  699.         string = "recv";
  700.         break;
  701.     case RPC_GETTIME:
  702.         string = "get time";
  703.         break;
  704.     case RPC_FS_PREFIX:
  705.         string = "prefix";
  706.         break;
  707.     case RPC_FS_OPEN:
  708.         string = "open";
  709.         break;
  710.     case RPC_FS_READ:
  711.         string = "read";
  712.         break;
  713.     case RPC_FS_WRITE:
  714.         string = "write";
  715.         break;
  716.     case RPC_FS_CLOSE:
  717.         string = "close";
  718.         break;
  719.     case RPC_FS_UNLINK:
  720.         string = "remove";
  721.         break;
  722.     case RPC_FS_RENAME:
  723.         string = "rename";
  724.         break;
  725.     case RPC_FS_MKDIR:
  726.         string = "mkdir";
  727.         break;
  728.     case RPC_FS_RMDIR:
  729.         string = "rmdir";
  730.         break;
  731.     case RPC_FS_MKDEV:
  732.         string = "make dev";
  733.         break;
  734.     case RPC_FS_LINK:
  735.         string = "link";
  736.         break;
  737.     case RPC_FS_SYM_LINK:
  738.         string = "link";
  739.         break;
  740.     case RPC_FS_GET_ATTR:
  741.         string = "get attrID";
  742.         break;
  743.     case RPC_FS_SET_ATTR:
  744.         string = "set attrID";
  745.         break;
  746.     case RPC_FS_GET_ATTR_PATH:
  747.         string = "get attr";
  748.         break;
  749.     case RPC_FS_SET_ATTR_PATH:
  750.         string = "set attr";
  751.         break;
  752.     case RPC_FS_GET_IO_ATTR:
  753.         string = "getI/Oattr";
  754.         break;
  755.     case RPC_FS_SET_IO_ATTR:
  756.         string = "setI/Oattr";
  757.         break;
  758.     case RPC_FS_DEV_OPEN:
  759.         string = "dev open";
  760.         break;
  761.     case RPC_FS_SELECT:
  762.         string = "select";
  763.         break;
  764.     case RPC_FS_IO_CONTROL:
  765.         string = "ioctl";
  766.         break;
  767.     case RPC_FS_CONSIST:
  768.         string = "consist";
  769.         break;
  770.     case RPC_FS_CONSIST_REPLY:
  771.         string = "cnsst rply";
  772.         break;
  773.     case RPC_FS_COPY_BLOCK:
  774.         string = "block copy";
  775.         break;
  776.     case RPC_FS_MIGRATE:
  777.         string = "mig file";
  778.         break;
  779.     case RPC_FS_RELEASE:
  780.         string = "release";
  781.         break;
  782.     case RPC_FS_REOPEN:
  783.         string = "reopen";
  784.         break;
  785.     case RPC_FS_RECOVERY:
  786.         string = "recov";
  787.         break;
  788.     case RPC_FS_DOMAIN_INFO:
  789.         string = "domain info";
  790.         break;
  791.     case RPC_PROC_MIG_COMMAND:
  792.         string = "mig cmd";
  793.         break;
  794.     case RPC_PROC_REMOTE_CALL:
  795.         string = "mig call";
  796.         break;
  797.     case RPC_PROC_REMOTE_WAIT:
  798.         string = "wait";
  799.         break;
  800.     case RPC_PROC_GETPCB:
  801.         string = "wait";
  802.         break;
  803.     case RPC_REMOTE_WAKEUP:
  804.         string = "wakeup";
  805.         break;
  806.     case RPC_SIG_SEND:
  807.         string = "signal";
  808.         break;
  809.     case RPC_FS_RELEASE_NEW:
  810.         string = "release new";
  811.         break;
  812.     default: {
  813.         sprintf(buffer,"%d",command);
  814.         string = buffer;
  815.         break;
  816.     }
  817.     }
  818.     fprintf(stream, format, string);
  819. }
  820.  
  821. /*
  822.  * PrintType --
  823.  *
  824.  *    Format and print the type field of the trace record.
  825.  */
  826. PrintType(stream, type, format)
  827.     FILE *stream;
  828.     int type;
  829.     char *format;
  830. {
  831.     char *string;
  832.     char buffer[20];
  833.  
  834.     switch(type) {
  835.     case RPC_INPUT:
  836.         string = "in";
  837.         break;
  838.     case RPC_OUTPUT:
  839.         string = "out";
  840.         break;
  841.     case RPC_CLIENT_a:        /* Client interrupt time stamps */
  842.     case RPC_CLIENT_b:
  843.     case RPC_CLIENT_c:
  844.     case RPC_CLIENT_d:
  845.     case RPC_CLIENT_e:
  846.     case RPC_CLIENT_f:
  847.         sprintf(buffer, "Ci %c ", type - RPC_CLIENT_a + 'a');
  848.         string = buffer;
  849.         break;
  850.     case RPC_CLIENT_A:        /* Client process level time stamps */
  851.     case RPC_CLIENT_B:
  852.     case RPC_CLIENT_C:
  853.     case RPC_CLIENT_D:
  854.     case RPC_CLIENT_E:
  855.     case RPC_CLIENT_F:
  856.         sprintf(buffer, "Cp %c ", type - RPC_CLIENT_A + 'A');
  857.         string = buffer;
  858.         break;
  859.     case RPC_SERVER_a:        /* Server interrupt time stamps */
  860.     case RPC_SERVER_b:
  861.     case RPC_SERVER_c:
  862.     case RPC_SERVER_d:
  863.     case RPC_SERVER_e:
  864.     case RPC_SERVER_f:
  865.         sprintf(buffer, "Ci %c ", type - RPC_SERVER_a + 'a');
  866.         string = buffer;
  867.         break;
  868.     case RPC_SERVER_A:        /* Server process level time stamps */
  869.     case RPC_SERVER_B:
  870.     case RPC_SERVER_C:
  871.     case RPC_SERVER_D:
  872.     case RPC_SERVER_E:
  873.     case RPC_SERVER_F:
  874.         sprintf(buffer, "Cp %c ", type - RPC_SERVER_A + 'A');
  875.         string = buffer;
  876.         break;
  877.     case RPC_CLIENT_OUT:
  878.         string = "Cexit";
  879.         break;
  880.     case RPC_SERVER_OUT:
  881.         string = "Sexit";
  882.         break;
  883.     default:
  884.         (void)sprintf(buffer,"%d",type);
  885.         string = buffer;
  886.     }
  887.     fprintf(stream, format, string);
  888. }
  889.  
  890.  
  891. /*
  892.  *----------------------------------------------------------------------
  893.  *
  894.  * PrintCltHist --
  895.  *
  896.  *    Print the client-side histogram numbers for each RPC command.
  897.  *
  898.  * Results:
  899.  *    None.
  900.  *
  901.  * Side effects:
  902.  *    None.
  903.  *
  904.  *----------------------------------------------------------------------
  905.  */
  906.  
  907. static void
  908. PrintCltHist()
  909. {
  910.     ReturnStatus status;
  911.     int cmdNum;            /* RPC command number */
  912.     Address buffer;        /* holds histogram struct & buckets */
  913.     char rpcName[RPC_MAX_NAME_LENGTH];
  914.  
  915.     buffer = malloc(sizeof(Rpc_Histogram) +
  916.             RPC_NUM_HIST_BUCKETS * sizeof(int));
  917.  
  918.     printf("RPC CLIENT HISTOGRAMS:\n");
  919.     for (cmdNum = 1; cmdNum <= RPC_LAST_COMMAND; ++cmdNum) {
  920.     Rpc_GetName(cmdNum, sizeof(rpcName), rpcName);
  921.     status = Sys_Stats(SYS_RPC_CLIENT_HIST, cmdNum, buffer);
  922.     if (status != SUCCESS) {
  923.         fprintf(stderr,
  924.             "Couldn't get clt histogram info for %s call (%d): %s\n",
  925.             rpcName, cmdNum, Stat_GetMsg(status));
  926.         return;
  927.     }
  928.     printf("  %s:\t", rpcName);
  929.     PrintHist(buffer);
  930.     }
  931.  
  932.     free(buffer);
  933. }
  934.  
  935.  
  936. /*
  937.  *----------------------------------------------------------------------
  938.  *
  939.  * PrintSrvHist --
  940.  *
  941.  *    Print the server-side histogram numbers for each RPC command.
  942.  *
  943.  * Results:
  944.  *    None.
  945.  *
  946.  * Side effects:
  947.  *    None.
  948.  *
  949.  *----------------------------------------------------------------------
  950.  */
  951.  
  952. static void
  953. PrintSrvHist()
  954. {
  955.     ReturnStatus status;
  956.     int cmdNum;            /* RPC command number */
  957.     Address buffer;        /* holds histogram struct & buckets */
  958.     char rpcName[RPC_MAX_NAME_LENGTH];
  959.  
  960.     buffer = malloc(sizeof(Rpc_Histogram) +
  961.             RPC_NUM_HIST_BUCKETS * sizeof(int));
  962.  
  963.     printf("RPC SERVER HISTOGRAMS:\n");
  964.     for (cmdNum = 1; cmdNum <= RPC_LAST_COMMAND; ++cmdNum) {
  965.     Rpc_GetName(cmdNum, sizeof(rpcName), rpcName);
  966.     status = Sys_Stats(SYS_RPC_SERVER_HIST, cmdNum, buffer);
  967.     if (status != SUCCESS) {
  968.         fprintf(stderr,
  969.             "Couldn't get srv histogram info for %s call (%d): %s\n",
  970.             rpcName, cmdNum, Stat_GetMsg(status));
  971.         return;
  972.     }
  973.     printf("  %s:\t", rpcName);
  974.     PrintHist(buffer);
  975.     }
  976.  
  977.     free(buffer);
  978. }
  979.  
  980.  
  981. /*
  982.  *----------------------------------------------------------------------
  983.  *
  984.  * PrintHist --
  985.  *
  986.  *    Print out numbers from a single histogram.
  987.  *
  988.  * Results:
  989.  *    None.
  990.  *
  991.  * Side effects:
  992.  *    None.
  993.  *
  994.  *----------------------------------------------------------------------
  995.  */
  996.  
  997. static void
  998. PrintHist(buffer)
  999.     Address buffer;        /* histogram struct, followed by counters */
  1000. {
  1001.     Rpc_Histogram *histPtr;
  1002.     int *countPtr;
  1003.     int firstBucket;        /* number of first bucket in row */
  1004.     int numCols = 8;        /* number of columns in the table of counts */
  1005.     int column;            /* which column in the table */
  1006.  
  1007.     histPtr = (Rpc_Histogram *)buffer;
  1008.     countPtr = (int *)(buffer + sizeof(Rpc_Histogram));
  1009.  
  1010.     Time_Divide(histPtr->totalTime, histPtr->numCalls,
  1011.         &histPtr->aveTimePerCall);
  1012.     printf("%d Calls,  ave %d.%06d secs each (%d.%06d sec overhead)\n",
  1013.        histPtr->numCalls, histPtr->aveTimePerCall.seconds,
  1014.        histPtr->aveTimePerCall.microseconds,
  1015.        histPtr->overheadTime.seconds,
  1016.        histPtr->overheadTime.microseconds);
  1017.  
  1018.     firstBucket = 0;
  1019.     /* 
  1020.      * There are numBuckets + 1 buckets to print (the +1 is for the 
  1021.      * overflow bucket).
  1022.      */
  1023.     while (firstBucket < histPtr->numBuckets + 1) {
  1024.     for (column = 0; column < numCols; ++column) {
  1025.         if (firstBucket + column >= histPtr->numBuckets) {
  1026.         break;
  1027.         }
  1028.         printf("%8d ", (firstBucket + column) * histPtr->usecPerBucket);
  1029.     }
  1030.     if (column < numCols && firstBucket + column == histPtr->numBuckets) {
  1031.         printf("Overflow");
  1032.         ++column;
  1033.     }
  1034.     printf("\n");
  1035.     for (column = 0; column < numCols; ++column) {
  1036.         if (firstBucket + column >= histPtr->numBuckets) {
  1037.         break;
  1038.         }
  1039.         printf("%7d  ", countPtr[firstBucket+column]);
  1040.     }
  1041.     if (column < numCols && firstBucket + column == histPtr->numBuckets) {
  1042.         printf("%7d\n", histPtr->numHighValues);
  1043.         ++column;
  1044.     }
  1045.     printf("\n\n");
  1046.     firstBucket += column;
  1047.     }
  1048. }
  1049.